/*
*  Copyright (c) 2006-2020, Chukie
*
*  SPDX-License-Identifier: Apache-2.0
*
*  @file     : cmux.h
*
*  @brief    :
*  Website   : https://gitee.com/open-embedded
*
*
*  Change Logs:
*  Date           Author          Notes
*  2020-06-28     zhaocj       The first version
*/
/* Define to prevent recursive inclusion ------------------------------------*/
#ifndef __CMUX_H__
#define __CMUX_H__
/* Includes -----------------------------------------------------------------*/
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#ifdef __cplusplus
extern "C"
{
#endif /*__cplusplus*/

#if CELLULAR_CMUX_CHANNEL_NUM >= 8
#error "CELLULAR_CMUX_CHANNEL_NUM >= 8"
#endif /*CELLULAR_CMUX_CHANNEL_NUM*/
/* Exported types -----------------------------------------------------------*/
#define CMUX_THREAD_PRIO                    1
#define CMUX_THREAD_STACK_SIZE              2048

typedef enum{
    CMUX_STATE_PARSE_START = 0,
    CMUX_STATE_PARSE_ADDR,
    CMUX_STATE_PARSE_CTRL,
    CMUX_STATE_PARSE_LEN,
    CMUX_STATE_PARSE_INFO,
    CMUX_STATE_PARSE_FCS,
    CMUX_STATE_PARSE_END
}cmux_state_t;

typedef struct cmux cmux_t;

typedef struct cmux_channel
{
    cmux_t *parent;
    int dlci;
    struct rt_device device;
    struct rt_ringbuffer rb;
    uint8_t *buffer;
} cmux_channel_t;

struct cmux
{
    char name[RT_NAME_MAX];
    volatile rt_bool_t running;
    struct rt_thread thread;
    struct rt_event event;
    struct rt_mutex write_lock;
    struct rt_semaphore tx_sem;
    rt_device_t device;
    uint32_t advance_mode : 16;
    uint32_t state : 16;
    cmux_channel_t channel_list[CELLULAR_CMUX_CHANNEL_NUM];
    uint32_t recv_len;
    uint8_t recv_buf[CMUX_FRAME_BUFFER_SIZE];
    rt_slist_t list;
    uint8_t stack[CMUX_THREAD_STACK_SIZE];
};


/* Exported constants -------------------------------------------------------*/
#define CMUX_EVENT_READ_DONE            (1<<0)
#define CMUX_EVENT_EXIT_REQ             (1<<2)
#define CMUX_EVENT_EXIT_ACK             (1<<3)

#define CMUX_EVENT_CHANNEL_CREATE_REQ_MASK  (0xFF<<16)
#define CMUX_EVENT_CHANNEL_CREATE_REQ(c)   (1<<(16+c))
#define CMUX_EVENT_CHANNEL_CREATE_ACK(c)   (1<<(24+c))
/* Exported macro -----------------------------------------------------------*/
#define CMUX_BASIC_FLAG                 (0xF9)
#define CMUX_ADVANCE_FLAG               (0x7E)

#define CMUX_ADDRESS_EA                 (1<<0)
#define CMUX_ADDRESS_CR                 (1<<1) //commnader is 1, responser is 0

#define CMUX_CONTROL_PF                 (1<<4)

#define CMUX_FRAME_TYPE_SABM            (0x2F)
#define CMUX_FRAME_TYPE_UA              (0x63)
#define CMUX_FRAME_TYPE_DM              (0x0F)
#define CMUX_FRAME_TYPE_DISC            (0x43)
#define CMUX_FRAME_TYPE_UIH             (0xEF)
#define CMUX_FRAME_TYPE_UI              (0x03)

#define CMUX_DATA_LEN_EA                (1<<0)
#define CMUX_DATA_LEN_LOW_MAX           (127)
#define CMUX_DATA_LEN_HIGH_MAX          (255<<7)

#define CMUX_MAX_DHCL_NUM               (63)
/* Exported functions -------------------------------------------------------*/

#define CMUX_ERR(fmt,...)    LOG_E("(%s:%d) "fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)
#define CMUX_WARN(fmt,...)   LOG_W("(%s:%d) "fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)
#define CMUX_INFO            LOG_I

#ifdef CELLULAR_CMUX_USING_DEBUG
    #define CMUX_DBG(fmt,...)       LOG_D("(%s:%d) "fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)
#else
    #define CMUX_DBG(fmt,...)
#endif

#define CMUX_CHECK_
    int cmux_init(cmux_t *cmux, const char *uart_name, int advance_mode);
    int cmux_add_channel(cmux_t *cmux, const char *name, rt_uint16_t flags, size_t buf_size);
    int cmux_start(cmux_t *cmux);
    int cmux_stop(cmux_t *cmux);
#ifdef __cplusplus
{
#endif /*__cplusplus*/
#endif /*__CMUX_H__*/
    /* End of file****************************************************************/

